#define _CRT_SECURE_NO_WARNINGS 1

// 模板初阶
//void Swap(int& left, int& right)
//{
//	int temp = left;
//	left = right;
//	right = temp;
//}
//
//void Swap(double& left, double& right)
//{
//	double temp = left;
//	left = right;
//	right = temp;
//}
//
//void Swap(char& left, char& right)
//{
//	char temp = left;
//	left = right;
//	right = temp;
//}

// 重载的函数仅仅是类型不同，代码复用率比较低
// 只要有新类型出现时，就需要用户自己增加对应的函数
// 代码的可维护性比较低，一个出错可能所有的重载均出错


// 泛型编程：编写与类型无关的通用代码，是代码复用的一种手段。模板是泛型编程的基础
// 函数模板代表了一个函数家族，该函数模板与类型无关
// 在使用时被参数化，根据实参类型产生函数的特定类型版本

//// 泛型编程
//// template<typename T1, typename T2, typename T3>
//#include <iostream>
//using namespace std;
//
//// 模板的原理是你需要什么，编译器帮助你实例化
//template<typename T>
//void Swap(T& left, T& right)
//{
//	T temp = left;
//	left = right;
//	right = temp;
//
//	cout << left << " " << right << endl;
//}
//
//int main()
//{
//	int a = 0, b = 1;
//	double c = 1.1, d = 2.2;
//	int* p1 = &a, * p2 = &b;
//
//	Swap(a, b);
//	Swap(c, d);
//	Swap(p1, p2);
//
//	return 0;
//}

//// 模板有隐式实例化，也有显式实例化
//#include <iostream>
//using namespace std;
//
//template <typename T>
//T Add(const T& left, const T& right)
//{
//	return left + right;
//}
//
//int main()
//{
//	int a1 = 10, a2 = 20;
//	double d1 = 10.1, d2 = 20.2;
//
//	Add(a1, a2);
//	Add(d1, d2);
//
//	cout << Add(a1, (int)d2) << endl;
//	cout << Add((double)a1, d2) << endl;
//
//	// 显式实例化
//	cout << Add<int>(a1, d2) << endl;
//	cout << Add<double>(a1, d2) << endl;
//
//	return 0;
//}

// 一个非模板函数可以和一个同名的函数模板同时存在
// 而且该函数模板还可以被实例化为这个非模板函数

//// 专门处理int的加法函数
//#include <iostream>
//using namespace std;
//
//int Add(int left, int right)
//{
//	cout << "int Add(int left, int right)" << endl;
//	return left + right;
//}
//
//// 通用加法函数
//template<class T>
//T Add(T left, T right)
//{
//	cout << "T Add(T left, T right)" << endl;
//	return left + right;
//}
//
//void Test()
//{
//	Add(1, 2); // 与非模板函数匹配，编译器不需要特化
//	Add<int>(1, 2); // 调用编译器特化的Add版本
//}
//
//int main()
//{
//	// 可以看出会优先匹配更匹配的
//	Test(); 
//
//	return 0;
//}

//// 有些时候，必须要显式实例化
//#include <iostream>
//using namespace std;
//
//template <class T>
//T* func(int a)
//{
//	T* p = (T*)operator new(sizeof(T));
//	new(p)T(a);
//
//	return p;
//}
//
//int main()
//{
//	int* ret1 = func<int>(1);
//	delete ret1;
//
//	return 0;
//}


// 类模版
// 模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误
template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 4)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
	void Push(const T& data)
	{
		_array[_size] = data;
		++_size;
	}
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
	Stack<int> st1;
	Stack<double> st2;

	return 0;
}